﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.Utilities;
using Workflows.Components.Entities.Distances;

namespace Workflows.Components.Entities
{
    [Serializable]
    public class EntityMetaData
    {
        private string _IdAttributeName;
        /// <summary></summary>
        public string IdAttributeName
        {
            get
            {
                return this._IdAttributeName;
            }
            set
            {
                this._IdAttributeName = value;
            }
        }

        private string _EntityCategory;
        /// <summary></summary>
        public string EntityCategory
        {
            get
            {
                return this._EntityCategory;
            }
            set
            {
                this._EntityCategory = value;
            }
        }

        private List<AttributeMetaData> _Attributes;
        /// <summary></summary>
        public List<AttributeMetaData> Attributes
        {
            get
            {
                return this._Attributes;
            }
            set
            {
                this._Attributes = value;
            }
        }

        private Dictionary<string, IAttributeDistanceCalcutor> _AttributeComparers;

        public EntityMetaData(string idAttrName, string category, List<AttributeMetaData> attrs)
        {
            this._IdAttributeName = idAttrName;
            this._EntityCategory = category;
            this._Attributes = attrs;

            this._AttributeComparers = new Dictionary<string, IAttributeDistanceCalcutor>();
            foreach(AttributeMetaData attrMetaData in this._Attributes)
            {
                this._AttributeComparers.Add(attrMetaData.AttributeName, attrMetaData.GetComparer());
            }
        }

        public double CompareEntity(Entity entity1, Entity entity2)
        {
            if (entity1 == entity2)
                return 1.0;
            double distance = 0;
            foreach (AttributeMetaData attributeMetaData in this.Attributes)
            {
                object attrValue1 = entity1.ComparableAttributes[attributeMetaData.AttributeName];
                object attrValue2 = entity2.ComparableAttributes[attributeMetaData.AttributeName];
                MatchResult matchResult = MatchResult.NullMatch;
                double attrDistance =  
                    this._AttributeComparers[attributeMetaData.AttributeName].Compare(attrValue1, attrValue2, ref matchResult);
                if (attrDistance > 0)
                    distance += attributeMetaData.PositiveMatchWeight * attrDistance;
                else if(matchResult==MatchResult.NegativeMatch)
                    distance += attributeMetaData.NegativeMatchWeight;
            }
            return distance;
        }

        
    }
}
